/************************************************************************
* opengl.c
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "common.h"
#include "graphics.h"

#include <string.h>

static struct {
	int anisotropic;
	float anisotropic_max;
	int cfg_anisotropic;
	int cfg_bilinear;
	int cfg_trilinear;
	int cfg_mipmap;
	int cfg_particles;
	int cfg_particles_max;
	int cfg_bumpmap;
	int cfg_pseudosdf;
	int cfg_max_shadow_passes;
	int cfg_shadow_size;
} opengl_features = {
	-1,
	1.0,
	0,
	0,
	1,
	1,
	1,
	1000,
	1,
	1,
	1,
	512
};

/* command anisotropic setter */
int opengl_anisotropic_setter(char* value)
{
	opengl_features.cfg_anisotropic = parse_bool(value);
	return 0;
}
/* command bilinear setter */
int opengl_bilinear_setter(char* value)
{
	opengl_features.cfg_bilinear = parse_bool(value);
	return 0;
}
/* command trilinear setter */
int opengl_trilinear_setter(char* value)
{
	opengl_features.cfg_trilinear = parse_bool(value);
	return 0;
}
/* command mipmap setter */
int opengl_mipmap_setter(char* value)
{
	opengl_features.cfg_mipmap = parse_bool(value);
	return 0;
}
/* command particles setter */
int opengl_particles_setter(char* value)
{
	opengl_features.cfg_particles = parse_bool(value);
	return 0;
}
/* command particlesmax setter */
int opengl_particles_max_setter(char* value)
{
	opengl_features.cfg_particles_max = strtol(value,NULL,10);
	return 0;
}
/* command bumpmap setter */
int opengl_bumpmap_setter(char* value)
{
	opengl_features.cfg_bumpmap = parse_bool(value);
	return 0;
}
/* command psdf setter */
int opengl_psdf_setter(char* value)
{
	opengl_features.cfg_pseudosdf = parse_bool(value);
	return 0;
}
/* command shadowpass setter */
int opengl_shadowpass_setter(char* value)
{
	opengl_features.cfg_max_shadow_passes = strtol(value,NULL,10);
	return 0;
}
/* command shadowsize setter */
int opengl_shadowsize_setter(char* value)
{
	opengl_features.cfg_shadow_size = strtol(value,NULL,10);
	return 0;
}

/* check for anisotropic filtering support */
int opengl_has_anisotropic()
{
	if (opengl_features.anisotropic < 0) {
		char* t = (char*)glGetString(GL_EXTENSIONS);
		opengl_features.anisotropic = 0;
		if (glGetError() == GL_NO_ERROR && t && strstr(t,"GL_EXT_texture_filter_anisotropic"))
			opengl_features.anisotropic = 1;
		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &opengl_features.anisotropic_max);
		if (glGetError() == GL_NO_ERROR)
			opengl_features.anisotropic_max = 1.0;
	}

	if (!opengl_features.anisotropic)
		return 0;

	if (opengl_features.cfg_anisotropic && opengl_features.cfg_mipmap)
		return 1;

	return 0;
}

/* get the maximum anisotropic filtering value */
float opengl_max_anisotropic()
{
	return opengl_features.anisotropic_max;
}

/* check for bilinear filtering support */
int opengl_has_bilinear()
{
	return opengl_features.cfg_bilinear;
}

/* check for trilinear filtering support */
int opengl_has_trilinear()
{
	return opengl_features.cfg_trilinear;
}

/* check for mipmap support */
int opengl_has_mipmap()
{
	return opengl_features.cfg_mipmap;
}

/* check if particle effects are enabled */
int opengl_has_particles()
{
	return opengl_features.cfg_particles;
}

/* get the maximum number of particles allowed */
int opengl_particles_max()
{
	if (!opengl_has_particles())
		return 0;
	return opengl_features.cfg_particles_max;
}

/* check if pseudo signed distance field rendering is enabled */
int opengl_has_psdf()
{
	return opengl_features.cfg_pseudosdf;
}

/* get the maximum number of shadow passes allowed */
int opengl_get_shadow_passes()
{
	return opengl_features.cfg_max_shadow_passes;
}

/* get the size of the shadow texture */
int opengl_get_shadow_size()
{
	return opengl_features.cfg_shadow_size;
}

/* converts an opengl error enum into a string */
char* opengl_error_string(GLenum e)
{
	/* TODO: moar! */
	switch (e) {
	case GL_INVALID_ENUM:
		return "OpenGL: GL_INVALID_ENUM";
		break;
	case GL_INVALID_VALUE:
		return "OpenGL: GL_INVALID_VALUE";
		break;
	case GL_INVALID_OPERATION:
		return "OpenGL: GL_INVALID_OPERATION";
		break;
	default:;
	}

	return "Unknown OpenGL Error";
}
